package main

import (
	"fmt"
	"os/exec"

	"github.com/ying32/govcl/vcl"
	"github.com/ying32/govcl/vcl/types"
)

// 创建代码生成页面
func (f *MainForm) createCoderFrame(i int) {
	var (
		top       int32 = commonPadding
		dbIndex   int32 = -1
		modeIndex int32 = -1
	)

	// 创建容器
	f.contentFrame[i] = vcl.NewFrame(f)
	f.contentFrame[i].SetParent(f)
	f.contentFrame[i].SetAlign(types.AlClient)
	f.contentFrame[i].SetColor(contentColor)

	// 数据源列表
	dbListLabel := vcl.NewLabel(f)
	dbListLabel.SetParent(f.contentFrame[i])
	dbListLabel.SetCaption("选择数据源")
	dbListLabel.SetBounds(custom5LabelPadding, top+labelFix, formLabelWidth, formItemHeight)
	f.coderFrame.dbList = vcl.NewComboBox(f)
	f.coderFrame.dbList.SetParent(f.contentFrame[i])
	f.coderFrame.dbList.SetBounds(formLabelWidth+commonPadding, top, formEditWidth, empty)
	f.coderFrame.dbList.SetStyle(types.CsDropDownList)
	f.coderFrame.dbList.SetOnCloseUp(func(sender vcl.IObject) {
		f.fixComboBoxErr()
	})
	f.coderFrame.dbList.SetOnSelect(func(sender vcl.IObject) {
		dbIndex = f.coderFrame.dbList.ItemIndex()
		if coderConfigs != nil && dbIndex <= int32(len(coderConfigs)-1) {
			modeIndex = coderConfigs[dbIndex].Mode
			vcl.ThreadSync(func() {
				f.coderFrame.tables.SetText(coderConfigs[dbIndex].Tables)
				f.coderFrame.basePath.SetText(coderConfigs[dbIndex].BasePath)
				f.coderFrame.mode.SetItemIndex(coderConfigs[dbIndex].Mode)
				f.coderFrame.basePackage.SetText(coderConfigs[dbIndex].BasePackage)
				f.onCoderModeChange(modeIndex)
			})
		} else {
			clear(f.coderFrame.tables, f.coderFrame.basePath, f.coderFrame.mode, f.coderFrame.basePackage)
		}
	})
	for _, config := range dbConfigs {
		f.coderFrame.dbList.Items().Add(config.DBId)
	}
	renderDBList := vcl.NewButton(f)
	renderDBList.SetParent(f.contentFrame[i])
	renderDBList.SetCaption("刷新数据源")
	renderDBList.SetBounds(f.coderFrame.dbList.Left()+f.coderFrame.dbList.Width()+commonPadding, top, formButtonWidth, formItemHeight)
	renderDBList.SetOnClick(func(sender vcl.IObject) {
		loadConfigs(0)
		vcl.ThreadSync(func() {
			clear(f.coderFrame.tables, f.coderFrame.basePath, f.coderFrame.mode, f.coderFrame.basePackage)
			f.coderFrame.dbList.Items().Clear()
			for _, dbConfig := range dbConfigs {
				f.coderFrame.dbList.Items().Add(dbConfig.DBId)
			}
			dbIndex = -1
		})
	})

	// 选择数据表
	top += commonPadding + formItemHeight
	f.coderFrame.tables = vcl.NewLabeledEdit(f)
	f.coderFrame.tables.SetParent(f.contentFrame[i])
	f.coderFrame.tables.EditLabel().SetCaption("选择数据表")
	f.coderFrame.tables.SetLabelPosition(types.LpLeft)
	f.coderFrame.tables.SetLabelSpacing(commonPadding)
	f.coderFrame.tables.SetReadOnly(true)
	f.coderFrame.tables.SetBounds(formLabelWidth+commonPadding, top, formEditWidth, empty)
	selectTables := vcl.NewButton(f)
	selectTables.SetParent(f.contentFrame[i])
	selectTables.SetBounds(f.coderFrame.tables.Left()+f.coderFrame.tables.Width()+commonPadding, top, formButtonWidth, formItemHeight)
	selectTables.SetCaption("选择表")
	selectTables.SetOnClick(func(sender vcl.IObject) {
		if dbIndex == -1 {
			vcl.ShowMessage("未选择数据源")
			return
		}
		f.selectTablesForm(dbIndex, func(tableStr string) {
			vcl.ThreadSync(func() {
				f.coderFrame.tables.SetText(tableStr)
			})
		})
	})

	// 生成位置
	top += commonPadding + formItemHeight
	f.coderFrame.basePath = vcl.NewLabeledEdit(f)
	f.coderFrame.basePath.SetParent(f.contentFrame[i])
	f.coderFrame.basePath.EditLabel().SetCaption("生成位置")
	f.coderFrame.basePath.SetLabelPosition(types.LpLeft)
	f.coderFrame.basePath.SetLabelSpacing(commonPadding)
	f.coderFrame.basePath.SetReadOnly(true)
	f.coderFrame.basePath.SetBounds(formLabelWidth+commonPadding, top, formEditWidth, empty)
	selectBasePath := vcl.NewButton(f)
	selectBasePath.SetParent(f.contentFrame[i])
	selectBasePath.SetCaption("选择文件夹")
	selectBasePath.SetBounds(f.coderFrame.basePath.Left()+f.coderFrame.basePath.Width()+commonPadding, top, formButtonWidth, formItemHeight)
	selectBasePath.SetOnClick(func(sender vcl.IObject) {
		if ok, dir := vcl.SelectDirectory1(0); ok {
			f.coderFrame.basePath.SetText(dir)
		}
	})

	// 选择生成模式
	top += commonPadding + formItemHeight
	modeLabel := vcl.NewLabel(f)
	modeLabel.SetParent(f.contentFrame[i])
	modeLabel.SetCaption("选择生成模式")
	modeLabel.SetBounds(custom6LabelPadding, top+labelFix, formLabelWidth, formItemHeight)
	f.coderFrame.mode = vcl.NewComboBox(f)
	f.coderFrame.mode.SetParent(f.contentFrame[i])
	f.coderFrame.mode.SetBounds(formLabelWidth+commonPadding, top, formEditWidth, empty)
	f.coderFrame.mode.SetStyle(types.CsDropDownList)
	f.coderFrame.mode.SetOnCloseUp(func(sender vcl.IObject) {
		f.fixComboBoxErr()
	})
	for i := 0; i < len(coderModes); i++ {
		f.coderFrame.mode.Items().Add(coderModes[i])
	}
	modeInfo := vcl.NewButton(f)
	modeInfo.SetParent(f.contentFrame[i])
	modeInfo.SetCaption("模式说明")
	modeInfo.SetBounds(f.coderFrame.mode.Left()+f.coderFrame.mode.Width()+commonPadding, top, formButtonWidth, formItemHeight)
	modeInfo.SetOnClick(func(sender vcl.IObject) {
		f.coderMode(func(i int32) {
			fmt.Println(i)
		})
	})

	// 生成包名
	f.coderFrame.basePackage = vcl.NewLabeledEdit(f)
	f.coderFrame.basePackage.SetParent(f.contentFrame[i])
	f.coderFrame.basePackage.EditLabel().SetCaption("生成类包名")
	f.coderFrame.basePackage.SetLabelPosition(types.LpLeft)
	f.coderFrame.basePackage.SetLabelSpacing(commonPadding)
	f.coderFrame.basePackage.SetBounds(formLabelWidth+commonPadding, top, formEditWidth, empty)
	f.coderFrame.basePackage.SetVisible(false)

	// 操作
	top += commonPadding*2 + formItemHeight
	f.coderFrame.exec = vcl.NewButton(f)
	f.coderFrame.exec.SetParent(f.contentFrame[i])
	f.coderFrame.exec.SetBounds(formLabelWidth+commonPadding, top, formButtonWidth, formItemHeight)
	f.coderFrame.exec.SetCaption("生成代码")
	f.coderFrame.exec.SetOnClick(func(sender vcl.IObject) {
		tablesText := f.coderFrame.tables.Text()
		basePathText := f.coderFrame.basePath.Text()
		basePackageText := f.coderFrame.basePackage.Text()
		if dbIndex == -1 || len(tablesText) == 0 || len(basePathText) == 0 || modeIndex == -1 {
			vcl.ShowMessage("数据填写不完整")
			return
		}
		exist := false
		if dbIndex <= int32(len(coderConfigs)-1) {
			for i := range coderConfigs {
				if coderConfigs[i].DBId == coderConfigs[dbIndex].DBId {
					exist = true
					coderConfigs[i].Tables = tablesText
					coderConfigs[i].BasePath = basePathText
					coderConfigs[i].BasePackage = basePackageText
					coderConfigs[i].Mode = modeIndex
					break
				}
			}
		}
		if !exist {
			coderConfig := CoderConfig{
				DBId:        dbConfigs[dbIndex].DBId,
				Tables:      tablesText,
				BasePath:    basePathText,
				BasePackage: basePackageText,
				Mode:        modeIndex,
			}
			coderConfigs = append(coderConfigs, coderConfig)
		}
		f.consoleForm.Show()
		go func() {
			f.runCoder(dbIndex, modeIndex, f.coderFrame.tables.Text(), f.coderFrame.basePath.Text(), f.coderFrame.basePackage.Text(), func(log string) {
				vcl.ThreadSync(func() {
					f.consoleLog.Lines().Add(log)
				})
			})
			reloadConfigs(1)
		}()
	})

	f.coderFrame.openDir = vcl.NewButton(f)
	f.coderFrame.openDir.SetParent(f.contentFrame[i])
	f.coderFrame.openDir.SetBounds(f.coderFrame.exec.Left()+f.coderFrame.exec.Width()+commonPadding, top, formButtonWidth, formItemHeight)
	f.coderFrame.openDir.SetCaption("打开目录")
	f.coderFrame.openDir.SetOnClick(func(sender vcl.IObject) {
		if len(f.coderFrame.basePath.Text()) == 0 {
			vcl.ShowMessage("未选择目录")
			return
		}
		_ = exec.Command(`cmd`, `/c`, `explorer`, f.coderFrame.basePath.Text()).Start()
	})

	f.coderFrame.mode.SetOnSelect(func(sender vcl.IObject) {
		modeIndex = f.coderFrame.mode.ItemIndex()
		f.onCoderModeChange(modeIndex)
	})

}

func (f *MainForm) onCoderModeChange(modeIndex int32) {
	top := f.coderFrame.mode.Top()
	if modeIndex == 0 {
		f.coderFrame.basePackage.SetVisible(false)
	} else if modeIndex == 1 || modeIndex == 3 {
		top += commonPadding + formItemHeight
		f.coderFrame.basePackage.SetVisible(true)
		f.coderFrame.basePackage.SetBounds(formLabelWidth+commonPadding, top, formEditWidth, empty)
	} else {
		f.coderFrame.basePackage.SetVisible(false)
	}
	top += commonPadding*2 + formItemHeight
	f.coderFrame.exec.SetBounds(formLabelWidth+commonPadding, top, formButtonWidth, formItemHeight)
	f.coderFrame.openDir.SetBounds(f.coderFrame.exec.Left()+f.coderFrame.exec.Width()+commonPadding, top, formButtonWidth, formItemHeight)
}
